#include "StdAfx.h"
#include "TextureSynthesis.h"
#include <iostream>
#include <cassert>


CTextureSynthesis::CTextureSynthesis(void)
{
	winWidth=5;
	winHeight=3;
}

CTextureSynthesis::~CTextureSynthesis(void)
{
}

bool CTextureSynthesis::LoadInput( const wchar_t * filename )
{
	return mInput.Load(filename);
}

bool CTextureSynthesis::LoadNoise( const wchar_t * filename )
{
	return mNoise.Load(filename);
}

void CTextureSynthesis::Process()
{

	mTimer.Reset();
	for (int i=0;i<mNoise.GetHeight();++i)
	{
		for (int j=0;j<mNoise.GetWidth();++j)
		{
			//BYTE pixel[winWidth*winHeight*3];
			BYTE pixel[300];
			GetPixelFromWin(&mNoise,j,i,pixel);
			float s=1e10;
			int x=0,y=0;
			for (int k=0;k<mInput.GetHeight();++k)
			{
				for(int l=0;l<mInput.GetWidth();++l)
				{
					//float tmp=Similarity(&mInput,&mNoise,l,k,j,i);
					float tmp=Similarity(&mInput,l,k,pixel);
					if (tmp<s)
					{
						s=tmp;
						x=l;
						y=k;
					}
				}
			}
			mNoise.SetPixelColor(j,i,mInput.GetPixelRed(x,y),
									mInput.GetPixelGreen(x,y),
									mInput.GetPixelBlue(x,y));	
			
			
		}
		system("cls");
		std::cout<<float(i)*100.0f/mNoise.GetHeight()<<"%"<<"compeleted"<<std::endl;
		
	}
	std::cout<<mTimer.GetElapse()<<" second(s)"<<std::endl;

}

void CTextureSynthesis::Process( int j,int i )
{
	BYTE pixel[300];
	GetPixelFromWin(&mNoise,j,i,pixel);
	float s=1e10;
	int x=0,y=0;
	for (int k=0;k<mInput.GetHeight();++k)
	{
		for(int l=0;l<mInput.GetWidth();++l)
		{
			float tmp=Similarity(&mInput,l,k,pixel);
			if (tmp<s)
			{
				s=tmp;
				x=l;
				y=k;
			}
		}
	}
	mNoise.SetPixelColor(j,i,mInput.GetPixelRed(x,y),
		mInput.GetPixelGreen(x,y),
		mInput.GetPixelBlue(x,y));	
}
float CTextureSynthesis::Distant( BYTE * a,BYTE * b )
{
	float ans=(*a-*b)*(*a-*b);
	++a,++b;
	ans+=(*a-*b)*(*a-*b);
	++a,++b;
	ans+=(*a-*b)*(*a-*b);
	return ans;
}

float CTextureSynthesis::Similarity( CTexture * tex1, CTexture * tex2, int x1, int y1,int x2,int y2 )
{
	float ans=0;
	for(int i=winHeight-1;i>0;--i){
		for (int j=-winWidth/2;j<winWidth/2;++j)
		{
			BYTE * a=tex1->GetPixelPtr((x1+j+tex1->GetWidth()*4)%tex1->GetWidth(),
										(y1-i+tex1->GetHeight()*4)%tex1->GetHeight());
			BYTE * b=tex2->GetPixelPtr((x2+j+tex2->GetWidth()*4)%tex2->GetWidth(),
				(y2-i+tex2->GetHeight()*4)%tex2->GetHeight());
			ans+=Distant(a,b);
		}
	}
	int i=0;
	for (int j=-winWidth/2;j<0;++j)
	{
		BYTE * a=tex1->GetPixelPtr((x1+j+tex1->GetWidth()*4)%tex1->GetWidth(),
			(y1-i+tex1->GetHeight()*4)%tex1->GetHeight());
		BYTE * b=tex2->GetPixelPtr((x2+j+tex2->GetWidth()*4)%tex2->GetWidth(),
			(y2-i+tex2->GetHeight()*4)%tex2->GetHeight());
		ans+=Distant(a,b);
	}
	return ans;

}

float CTextureSynthesis::Similarity( CTexture *tex1,int x1,int y1,BYTE* pixel/*,int length*/ )
{
	float ans=0;
	int index=0;
	int height=tex1->GetHeight();
	int width=tex1->GetWidth();
	for(int i=winHeight-1;i>0;--i)
	{
		for (int j=-winWidth/2;j<winWidth/2;++j)
		{
			BYTE * a=tex1->GetPixelPtr((x1+j+width*4)%width,(y1-i+height*4)%height);
			ans+=Distant(a,pixel+index*3);
			++index;
		}
	}
	int i=0;
	for (int j=-winWidth/2;j<0;++j)
	{
		BYTE * a=tex1->GetPixelPtr((x1+j+width*4)%width,(y1-i+height*4)%height);
		ans+=Distant(a,pixel+index*3);
		++index;
	}
//	assert(index==length);
	return ans;
}

void CTextureSynthesis::GetPixelFromWin( CTexture* tex1,int x1,int y1,BYTE * pixel )
{
	int index=0;
	int height=tex1->GetHeight();
	int width=tex1->GetWidth();
	for(int i=winHeight-1;i>0;--i)
	{
		for (int j=-winWidth/2;j<winWidth/2;++j)
		{
			BYTE * a=tex1->GetPixelPtr((x1+j+width*4)%width,(y1-i+height*4)%height);
			memcpy(pixel+index*3,a,3);
			++index;
		}
	}
	int i=0;
	for (int j=-winWidth/2;j<0;++j)
	{
		BYTE * a=tex1->GetPixelPtr((x1+j+width*4)%width,(y1-i+height*4)%height);
		memcpy(pixel+index*3,a,3);
		++index;
	}
}